// Boss.cpp //
//Boss class is mainly in charge of creation and destruction of a boss
#include "Boss.h"

#include "Sound.h"

Boss Boss::FinalBoss;

Boss::Boss()//Simple constructor
{
	boss = NULL;
	spawned = false;
	killed = false;
}

void Boss::RemoveBoss()// ends boss
{
	FinalBoss.boss = NULL;
	FinalBoss.spawned = false;
	FinalBoss.killed = false;
}

void Boss::SpawnBoss() // creates the boss, starts music
{
	FinalBoss.boss = new BossEnemy("Boss");
	FinalBoss.spawned = true;
	Sound::PlaySound("Boss");
}

void Boss::DestroyBoss() // when boss is killed
{
    FinalBoss.boss = NULL;
	FinalBoss.killed = true;
}

// BossEnemy.cpp //
//BossEnemy is the actual boss created, has health, sprite, ai, etc
// Other boss enemies could be created with diferent characteristics
// but still inheriting from boss
#include "Bullet.h"
#include "Player.h"

BossEnemy::BossEnemy(string keyname) : Enemy(keyname) // constructor
{
	pointValue = BossPointValue; //Boss is worth some number of points
	int rPrime = rand() % 34; // chooses initial prime displayed on boss
	int newPrime = Primes[rPrime];// ||
	this->numValue = newPrime;//     ||
	position = Vector(ScreenWidth / 2, -sprite->origin.Y);
	direction = Vector(0, 1); // boss initially moves down
	speed = BossSpeed;
	health = BossHealth; 

    childrenAngle = 0.0f; // initialise values
	fireAngle = 0.0f;
	lastFired = 0.0f;
	
	OrbL = new Miniboss("OrbL"); // create min bosses
	OrbR = new Miniboss("OrbR");
}

void BossEnemy::Update(float deltaTime) // updates at each game loop
{
	// num value set to -1 when hit numValue made divisible
	// we detect this and damage the boss, them reset the numValue
	// to a new prime number
	if(this->numValue == -1) 
	{
		this->TakeDamage(300);
		int rPrime = rand() % 34;
		int newPrime = Primes[rPrime];
		this->numValue = newPrime;
	}
	Enemy::Update(deltaTime); // updates enemy data

	UpdateChildren();
	
	//below if loop moves boss down then has it move back and forth sideways
	if(direction.X < 0) 
	{
	    if(position.X < 300)
	    	direction = Vector(1, 0);
	}
	else if(direction.X > 0)
	{
	    if(position.X > ScreenWidth - 300)
	    	direction = Vector(-1, 0);
	}
	else
	{
	    if(position.Y > ScreenHeight / 3)
	        if(rand() % 2 == 0)
	    		direction = Vector(1, 0);
	    	else
	    		direction = Vector(-1, 0);
	}

	childrenAngle += BossChildrenRotation;
	
	//harder near death
	if(health > BossHealth / 2)
	{
		fireAngle += BossFireRotation;
		lastFired += deltaTime;
	}
	else
	{
		fireAngle += BossFireRotation * 1.5;
		lastFired += deltaTime * 1.5;
	}
	    
	if(lastFired > BossFireDelay)
	    FireBullet();
}

//update the mini bosses
void BossEnemy::UpdateChildren()
{
	if(OrbL != NULL)
		if(OrbL->health > 0) // keeps children moving on the correct side of the boss
			OrbL->position = position + Vector(-200, 75) + Vector::CalculateDirection(-childrenAngle) * 25;
		else
	    	OrbL = NULL;
	    
	if(OrbR != NULL)
		if(OrbR->health > 0)
			OrbR->position = position + Vector(200, 75) + Vector::CalculateDirection(childrenAngle) * -25;
		else
	    	OrbR = NULL;
}

void BossEnemy::RemoveOffScreen()
{
	SDL_Rect bounds = {-ScreenWidth, -ScreenHeight, ScreenWidth * 3, ScreenHeight * 3};
	SDL_Rect intersect = Intersection(GetBounds(), bounds);

	if(intersect.w == 0 && intersect.h == 0)
	    Remove();
}

void BossEnemy::Remove()
{
	Boss::DestroyBoss();
	
	Enemy::Remove();
}

void BossEnemy::FireBullet() // contolls boss fire pattern
{
	Bullet* bullet = new Bullet("Big"); // choose bullet type
	bullet->position = position; // bullet starts in middle of boss
	bullet->direction = Vector::CalculateDirection(fireAngle); //aim bullet
	bullet->speed = 100.0f; // bullet speed
	bullet->CollisionList = &PlayerShip::PlayerShipList; // only check for collision with player 

    lastFired = 0.0f; // reset fired variable
}

void BossEnemy::Render(SDL_Surface* screen) // override default render for boss
{
	char buffer[4]; // holds num
	sprintf(buffer, "%d", this->numValue);
	sprite->Render(screen,position);// first render the sprite
	sprite->texture->DrawText(screen,buffer,50,this->position.X,this->position.Y,0,0,0,true); // then the number on top
}
